package clueless.server;

import java.util.ArrayList;

import clueless.utilities.Card;
import clueless.utilities.Logger;
import clueless.utilities.Message;
import clueless.utilities.StringPair;
import clueless.utilities.Suggestion;

public class GameServer extends Logger {

	private int               m_numDesiredPlayers;
	private ArrayList<Player> m_players;
	private Game              m_game;

	public GameServer(int desiredNumPlayers) {

		super("GameServer");
		m_numDesiredPlayers = desiredNumPlayers;
		m_players           = new ArrayList<Player>();
		m_game              = new Game();


	}

	public boolean isCharacterUnclaimed(String character) {
		
		for (int i = 0; i < m_players.size(); i++) {
			Player player = m_players.get(i);
			if (character.equalsIgnoreCase(player.getCharacter())) return false;
		}

		return true;

	}
	
	public void addPlayer(Player player) {
		m_players.add(player);
		m_game.addPlayer(player);
	}

	public int getNumDesiredPlayers() {
		return m_numDesiredPlayers;
	}

	public int getNumRemainingPlayers() {
		return m_numDesiredPlayers - m_players.size();
	}

	public ArrayList<Player> getPlayers() {
		return m_players;
	}
	
	private int calcNumActivePlayers() {

		int numActivePlayers = 0;

		for (int i = 0; i < m_players.size(); i++) {
			if(m_players.get(i).getIsStillPlaying()) numActivePlayers++;
		}

		return numActivePlayers;
	}

	private void playTurn() {
	
		m_game.endTurn();
		Message.sendStartTurnMessage(m_players, m_game.getCurrentPlayer());
		
		// TODO tell players about possible moves
		Message.sendTextMessageToOnePlayer(m_game.getCurrentPlayer(), m_game.getCurrentPlayer().getPossibleMoves(m_game.m_players));

		String message = Message.getMessage(m_game.getCurrentPlayer().getConnection().getInputStream());
		
		if (Message.getMessageType(message).equals(Message.m_PLAYER_ACCUSES)) {
			
			String character = Message.getValue(Message.m_CHARACTER, message);
			String weapon = Message.getValue(Message.m_WEAPON, message);
			String room = Message.getValue(Message.m_ROOM, message);
			Suggestion suggestion = new Suggestion(character, weapon, room);
			processAccusation(suggestion);

		} else if (Message.getMessageType(message).equals(Message.m_PLAYER_MOVES)) {
			String movement = Message.getValue(Message.m_MOVEMENT, message);
			processMovement(movement);
		}

	}
	
	private void processMovement(String movement) {
		Player player = m_game.getCurrentPlayer();
		player.move(movement);
		Message.sendPlayerMovement(m_game.m_players, player.getCharacter(), player.getRoom().getMyRoom());
		if (player.inRoom()) {
			Message.sendRequestSuggestionMessage(player);
			processSuggestion();
		} else {
			playTurn();
		}
		
	}

	private void processSuggestion() {
		
		// Get suggestion from current player
		Suggestion suggest = receiveSuggestion();
		
		// Move suggested player to suggested room
		m_game.MovePlayerToRoom(suggest.getCharacter(), suggest.getRoom());
		
		// Inform players of movement
		Message.sendPlayerMovement(m_players, suggest.getCharacter(), suggest.getRoom());
		
		// Inform players of suggestion
		Message.sendTextMessageToAllPlayers(m_players, 
				m_game.getCurrentPlayer().getCharacter() + " suggests " + suggest.getCharacter() + 
				" in the " + suggest.getRoom() + 
				" with the " + suggest.getWeapon());
		
		
		// Get Refute from next player
		// Keep going until either a player can refute or we have tried all players
		int nextPlayer = 1;
		while (m_game.getCurrentPlayer() != m_game.getPlayer(nextPlayer)) {
			Message.sendGetRefute(m_game.getPlayer(nextPlayer), suggest);
			
			// Get message from Player.  It will either by a m_PLAYER_REFUTES or a m_PLAYER_CANNOT_REFUTE message
			String message = Message.getMessage(m_game.getPlayer(nextPlayer).getConnection().getInputStream());
			
			if (Message.getMessageType(message).equals(Message.m_PLAYER_REFUTES)) {
				// If we got a Refute message inform current player
				Message.sendRefuteToPlayer(m_game.getCurrentPlayer(), message);
				playTurn();
				return;
			} else if(Message.getMessageType(message).equals(Message.m_PLAYER_CANNOT_REFUTE)) {
				// If player unable to refute inform all players and go to next player
				Message.sendTextMessageToAllPlayers(m_players, m_game.getPlayer(nextPlayer).getCharacter() + " was unable to refute suggestion. ");
				nextPlayer++;
			}
		}
		
		Message.sendAllPlayersCannotRefute(m_game.getCurrentPlayer());
		playTurn();
		//Message.sendRequestAccusation(m_game.getCurrentPlayer());
		
//		String message = Message.getMessage(m_game.getCurrentPlayer().getConnection().getInputStream());
//		String character = Message.getValue(Message.m_CHARACTER, message);
//		String weapon = Message.getValue(Message.m_WEAPON, message);
//		String room = Message.getValue(Message.m_ROOM, message);
//		Suggestion suggestion = new Suggestion(character, weapon, room);
//		processAccusation(suggestion);
	}

	private Suggestion receiveSuggestion() {
		String message = Message.getMessage(m_game.getCurrentPlayer().getConnection().getInputStream());
		
		String character = Message.getValue(Message.m_CHARACTER, message);
		String weapon = Message.getValue(Message.m_WEAPON, message);
		String room = Message.getValue(Message.m_ROOM, message);
		Suggestion suggestion = new Suggestion(character, weapon, room);
		return suggestion;
	}

	private void processAccusation(Suggestion suggestion) {
		if (m_game.verifyAccusation(suggestion)) {
			Message.sendPlayerWinsByDefaultMessage(m_players, m_game.getCurrentPlayer(), m_game.getSolution());
			endGame();
		} else if (this.calcNumActivePlayers() == 1) {
			Message.sendPlayerWinsByDefaultMessage(m_players, m_game.getNextActivePlayer(), m_game.getSolution());
			endGame();
		} else {
			Message.sendTextMessageToAllPlayers(m_players, m_game.getCurrentPlayer().getCharacter() + " is removed from game for incorrect accusation");
		}
		playTurn();
	}

	private void endGame() {
		System.exit(0);
	}

	public void playGame() {

		// Alert players that game is beginning
		Message.sendStartGameMessage(m_players);
		
		m_game.distributeCards();
		
		for (Player player : m_players) {
			
//			String cards = player.getCards();
//			System.out.println(player.getCharacter() + "'s cards are: " + cards);
//			Message.sendTextMessageToOnePlayer(player, "Your cards are - " + cards);
//			Message.sendPlayerCardsMessage(player, cards);

//			String[] cards = player.getCards().split(",");
//
//			ArrayList<StringPair> cardList;
//			for (int i = 0; i < cards.length; i++) {
//				if      (Card.isCharacter(cards[i])) cardList.add(new StringPair(Message.m_CHARACTER, cards[i]));
//				else if (Card.isWeapon   (cards[i])) cardList.add(new StringPair(Message.m_WEAPON   , cards[i]));
//				else                                 cardList.add(new StringPair(Message.m_ROOM     , cards[i]));
//			}
			
			String cardString = player.getCards();
			System.out.println(player.getCharacter() + "'s cards are: " + cardString);
			String[] cards = cardString.split(",");
			Message.sendTextMessageToOnePlayer(player, "Your cards are:");
			for (int i = 0; i < cards.length; i++) Message.sendTextMessageToOnePlayer(player, cards[i]);
			Message.sendPlayerCardsMessage(player, cards);
		}
		
		playTurn();

	}

}
